﻿using System;
using System.Net.Sockets;
using System.Net;
using System.Text;
using System.Threading;
using Newtonsoft.Json;
using System.Reflection;
using System.Collections.Generic;
using socket_server.Transport_Protocol;

namespace socket_server
{
    public class Program
    {
        private static Socket ServerSocket;
        private static string IP = "10.246.34.190";//"192.168.56.1";
        private static int Port = 30000;

        private static CBindCmd cBindCmd = new CBindCmd();
        private static Dictionary<int, string> CM_Dictionary = new Dictionary<int, string>();
        private static Dictionary<int, string> SM_Dictionary = new Dictionary<int, string>();

        private static CPlayer cPlayer = new CPlayer();
        private static Dictionary<int, string> DoCM_Dictionary = new Dictionary<int, string>();

        private static Dictionary<string, Socket> DICClientSocket = new Dictionary<string, Socket>();//用于存储已连接的客户端
        private static Dictionary<string, CPlayer> DICClientCPlayer = new Dictionary<string, CPlayer>();//用于记录客户端的玩家

        public static void Main(string[] args)
        {
            CM_Dictionary = cBindCmd.GetCM_Dictionary();
            SM_Dictionary = cBindCmd.GetSM_Dictionary();
            DoCM_Dictionary = cBindCmd.GetDoCM_Dictionary();

            //定义一个套接字用于监听客户端发来的消息，包含三个参数（IP4寻址协议，流式连接，Tcp协议）
            ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //服务端发送信息需要一个IP地址和端口号
            IPAddress Address = IPAddress.Parse(IP);
            //将IP地址和端口号绑定到网络节点point上
            IPEndPoint Point = new IPEndPoint(Address, Port);
            //此端口专门用来监听的

            //监听绑定的网络节点
            ServerSocket.Bind(Point);

            //将套接字的监听队列长度限制为200
            ServerSocket.Listen(20000);

            //负责监听客户端的线程:创建一个监听线程
            Thread threadwatch = new Thread(WatchConnecting);
            //将窗体线程设置为与后台同步，随着主线程结束而结束
            threadwatch.IsBackground = true;
            //启动线程
            threadwatch.Start();

            Console.WriteLine("开启监听。。。");
            Console.WriteLine("点击输入Exit然后回车退出程序。。。");
            while (true)
            {
                string inputStr = Console.ReadLine();
                if (inputStr == "Exit")
                {
                    Console.WriteLine("5秒后退出监听，并关闭程序。");
                    Thread.Sleep(5000);
                    System.Environment.Exit(0);
                }                
            }
            //Console.WriteLine("开启监听。。。");
            //Console.WriteLine("点击输入任意数据回车退出程序。。。");
            //Console.ReadKey();
            //Console.WriteLine("退出监听，并关闭程序。");
        }

        //监听客户端发来的请求
        public static void WatchConnecting()
        {
            Socket connection = null;
            //持续不断监听客户端发来的请求
            while (true)
            {
                try
                {
                    connection = ServerSocket.Accept();
                }
                catch (Exception ex)
                {
                    //提示套接字监听异常
                    Console.WriteLine(ex.Message);
                    break;
                }

                //获取客户端的IP和端口号
                IPAddress clientIP = (connection.RemoteEndPoint as IPEndPoint).Address;
                int clientPort = (connection.RemoteEndPoint as IPEndPoint).Port;

                //让客户显示"连接成功的"的信息
                //string sendmsg = "连接服务端成功！\r\n" + "本地IP:" + clientIP + "，本地端口" + clientPort.ToString();
                //byte[] arrSendMsg = Encoding.UTF8.GetBytes(sendmsg);
                //connection.Send(arrSendMsg);

                //客户端网络结点号
                string remoteEndPoint = connection.RemoteEndPoint.ToString();
                //显示与客户端连接情况
                Console.WriteLine("成功与" + remoteEndPoint + "客户端建立连接！\t\n");
                //添加客户端信息
                DICClientSocket.Add(remoteEndPoint, connection);

                //客户端建立CPlayer对象
                CPlayer Player = new CPlayer();
                //添加客户端Player信息
                DICClientCPlayer.Add(remoteEndPoint, Player);

                //IPEndPoint netpoint = new IPEndPoint(clientIP,clientPort);
                IPEndPoint netpoint = connection.RemoteEndPoint as IPEndPoint;

                //创建一个通信线程
                ParameterizedThreadStart PTS_Recv = new ParameterizedThreadStart(Recv);
                Thread T_PTS_Recv = new Thread(PTS_Recv);
                //设置为后台线程，随着主线程退出而退出
                T_PTS_Recv.IsBackground = true;
                //启动线程
                T_PTS_Recv.Start(connection);

                ////创建一个通信线程
                //ParameterizedThreadStart PTS_Send = new ParameterizedThreadStart(Send);
                ////开启新线程来不停发送信息
                //Thread T_PTS_Send = new Thread(PTS_Send);
                ////设置为后台线程，随着主线程退出而退出
                //T_PTS_Send.IsBackground = true;
                ////启动线程
                //T_PTS_Send.Start(connection);

                //设置客户端的CBaseRemoteEndPointStr
                CSM_SetCBaseRemoteEndPointStr cSM_SetCBaseRemoteEndPointStr = new CSM_SetCBaseRemoteEndPointStr()
                {
                    CBaseClassID = CServerToClientClass.SM_SetCBaseRemoteEndPointStr,
                    CBaseRemoteEndPointStr = remoteEndPoint,
                };

                JsonSerializerSettings jsonSerializerSettings = new JsonSerializerSettings();
                jsonSerializerSettings.DefaultValueHandling = DefaultValueHandling.Ignore;
                //序列化为Json格式
                string json = JsonConvert.SerializeObject(cSM_SetCBaseRemoteEndPointStr, cSM_SetCBaseRemoteEndPointStr.GetType(), Formatting.None, jsonSerializerSettings);
                //编码
                byte[] buffer = Encoding.UTF8.GetBytes(json);
                //发送
                connection.Send(buffer);
            }
        }
        public static void Recv(object socketclientpara)
        {
            Socket socketServer = socketclientpara as Socket;
            string remoteEndPoint = socketServer.RemoteEndPoint.ToString();
            while (true)
            {
                if (socketServer.Connected == false)
                {
                    return;
                }

                //创建一个内存缓冲区，其大小为1024*1024字节  即1M
                byte[] arrServerRecMsg = new byte[1024 * 1024];
                //将接收到的信息存入到内存缓冲区，并返回其字节数组的长度
                try
                {
                    int length = socketServer.Receive(arrServerRecMsg);
                    if (length != 0)
                    {
                        //将机器接受到的字节数组转换为人可以读懂的字符串
                        string strSRecMsg = Encoding.UTF8.GetString(arrServerRecMsg, 0, length);

                        //将发送的字符串信息附加到文本框txtMsg上
                        //Console.WriteLine("客户端:" + socketServer.RemoteEndPoint + ",time:" + GetCurrentTime() + "\r\n" + strSRecMsg + "\r\n\n");
                        Console.WriteLine("");
                        Console.WriteLine("***以下是客户端发送内容***" + "***当前时间：" + DateTime.Now.ToString() + "***");
                        Console.WriteLine("客户端说：" + strSRecMsg);
                        CBaseClass cBaseClass = JsonConvert.DeserializeObject<CBaseClass>(strSRecMsg);
                        if (cBaseClass != null)
                        {
                            string TypeName = CM_Dictionary[cBaseClass.CBaseClassID];
                            if (!string.IsNullOrEmpty(TypeName))
                            {
                                var CM_Msg = JsonConvert.DeserializeObject(strSRecMsg, Type.GetType(TypeName));
                                if (CM_Msg != null)
                                {
                                    string MethodName = DoCM_Dictionary[cBaseClass.CBaseClassID];
                                    if (!string.IsNullOrEmpty(MethodName))
                                    {
                                        CPlayer Player = DICClientCPlayer[remoteEndPoint];
                                        if (Player != null)
                                        {
                                            Type type = Player.GetType();
                                            MethodInfo method = type.GetMethod(MethodName);
                                            object[] arrParams = { CM_Msg };
                                            method.Invoke(Player, arrParams);
                                        }
                                    }
                                }
                            }
                        }
                        else if (!string.IsNullOrEmpty(strSRecMsg) && cBaseClass == null)
                        {
                            Console.WriteLine("客户端协议序列化失败！");
                        }
                        Console.WriteLine("***以上是客户端发送内容***" + "***当前时间：" + DateTime.Now.ToString() + "***");
                        Console.WriteLine("");
                    }
                }
                catch (Exception ex)
                {
                    DICClientSocket.Remove(remoteEndPoint);
                    Console.WriteLine("ClientSocketCount:" + DICClientSocket.Count);
                    DICClientCPlayer.Remove(remoteEndPoint);
                    Console.WriteLine("ClientPlayerCount:" + DICClientCPlayer.Count);

                    //提示套接字监听异常
                    Console.WriteLine("客户端" + socketServer.RemoteEndPoint + "已经中断连接" + "\r\n" + ex.Message + "\r\n" + ex.StackTrace + "\r\n");
                    //关闭之前accept出来的和客户端进行通信的套接字
                    socketServer.Close();
                    break;
                }
            }
        }

        /// <summary>
        /// 获取当前系统时间的方法
        /// </summary>
        /// <returns></returns>
        public static DateTime GetCurrentTime()
        {
            DateTime currentTime = new DateTime();
            currentTime = DateTime.Now;
            return currentTime;
        }

        public static void Listen(object so)
        {
            Socket serverSocket = so as Socket;

            while (true)
            {
                try
                {
                    Socket clientSocket = serverSocket.Accept(); //接受客户端接入
                    // 获取链接IP地址
                    string clientPoint = clientSocket.RemoteEndPoint.ToString();

                    //开启新线程来不停接受信息
                    Thread rec = new Thread(Receive);
                    rec.Start(clientSocket);

                    //开启新线程来不停发送信息
                    //Thread send = new Thread(Send);
                    //send.Start(clientSocket);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message, ex);
                    break;
                }
            }
            serverSocket.Close();
        }

        public static void Receive(object so)
        {
            Socket clientSocket = so as Socket;

            string clientPoint = clientSocket.RemoteEndPoint.ToString();
            while (true)
            {
                try
                {
                    byte[] buffer = new byte[1024];
                    int len = clientSocket.Receive(buffer);
                    if (len == 0) break;

                    string msg = Encoding.UTF8.GetString(buffer, 0, len);
                    Console.WriteLine("");
                    Console.WriteLine("***以下是客户端发送内容***" + "***当前时间：" + DateTime.Now.ToString() + "***");
                    Console.WriteLine("客户端说：" + msg);
                    CBaseClass cBaseClass = JsonConvert.DeserializeObject<CBaseClass>(msg);
                    if (cBaseClass != null)
                    {
                        string TypeName = CM_Dictionary[cBaseClass.CBaseClassID];
                        if (!string.IsNullOrEmpty(TypeName))
                        {
                            var CM_Msg = JsonConvert.DeserializeObject(msg, Type.GetType(TypeName));
                            if (CM_Msg != null)
                            {

                                string MethodName = DoCM_Dictionary[cBaseClass.CBaseClassID];
                                if (!string.IsNullOrEmpty(MethodName))
                                {
                                    Type type = cPlayer.GetType();
                                    MethodInfo method = type.GetMethod(MethodName);
                                    object[] arrParams = { CM_Msg };
                                    method.Invoke(cPlayer, arrParams);
                                }
                            }
                        }
                    }
                    Console.WriteLine("***以上是客户端发送内容***" + "***当前时间：" + DateTime.Now.ToString() + "***");
                    Console.WriteLine("");
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex);
                    System.Environment.Exit(0);
                }
            }
        }

        //public static void Send(object so)
        //{
        //    Socket clientSocket = so as Socket;
        //    string clientPoint = clientSocket.RemoteEndPoint.ToString();
        //    while (true)
        //    {
        //        try
        //        {
        //            if (DICcBaseClassList != null && DICcBaseClassList.Count > 0)
        //            {
        //                List<CBaseClass> cBaseClassList = DICcBaseClassList[clientPoint];
        //                if (cBaseClassList != null && cBaseClassList.Count > 0)
        //                {
        //                    for (int I = 0; I <= cBaseClassList.Count - 1; I++)
        //                    {
        //                        CBaseClass cBaseClass = cBaseClassList[I];
        //                        if (cBaseClass != null)
        //                        {
        //                            string TypeName = SM_Dictionary[cBaseClass.CBaseClassID];
        //                            if (!string.IsNullOrEmpty(TypeName))
        //                            {
        //                                JsonSerializerSettings jsonSerializerSettings = new JsonSerializerSettings();
        //                                jsonSerializerSettings.DefaultValueHandling = DefaultValueHandling.Ignore;

        //                                //序列化为Json格式
        //                                string json = JsonConvert.SerializeObject(cBaseClass, Type.GetType(TypeName), Formatting.None, jsonSerializerSettings);
        //                                //编码
        //                                byte[] buffer = Encoding.UTF8.GetBytes(json);
        //                                //发送
        //                                if (clientSocket != null && clientSocket.Connected == true)
        //                                {
        //                                    clientSocket.Send(buffer);
        //                                }
        //                            }
        //                            cBaseClassList.RemoveAt(I);
        //                        }
        //                    }
        //                    //Thread.Sleep(5000);
        //                }
        //            }
        //        }
        //        catch (Exception ex)
        //        {
        //            Console.WriteLine("Send错误信息：" + ex.Message, ex);
        //            Console.WriteLine("DICcBaseClassList数量" + DICcBaseClassList.Count.ToString());
        //            break;
        //        }
        //        finally
        //        {

        //        }
        //    }
        //    ////获取控制台输入
        //    //string input = Console.ReadLine();
        //    //CSM_Test cSM_DoTest = new CSM_Test()
        //    //{
        //    //    CBaseClassID = CServerToClientClass.SM_Test,
        //    //    Desc = input,
        //    //};
        //    ////序列化为Json格式
        //    //string json = JsonConvert.SerializeObject(cSM_DoTest, Formatting.None);
        //    ////编码
        //    //byte[] buffer = Encoding.UTF8.GetBytes(json);
        //    ////发送
        //    //clientSocket.Send(buffer);
        //}
        public static void AddClientMsg(CBaseClass cBaseClass)
        {
            if ((cBaseClass == null))
            {
                return;
            }

            try
            {
                if (DICClientSocket != null && DICClientSocket.Count > 0)
                {
                    Socket clientSocket = DICClientSocket[cBaseClass.CBaseRemoteEndPointStr];

                    if ((clientSocket == null) || (clientSocket.Connected == false))
                    {
                        return;
                    }

                    string TypeName = SM_Dictionary[cBaseClass.CBaseClassID];
                    if (!string.IsNullOrEmpty(TypeName))
                    {
                        JsonSerializerSettings jsonSerializerSettings = new JsonSerializerSettings();
                        jsonSerializerSettings.DefaultValueHandling = DefaultValueHandling.Ignore;

                        //序列化为Json格式
                        string json = JsonConvert.SerializeObject(cBaseClass, Type.GetType(TypeName), Formatting.None, jsonSerializerSettings);
                        //编码
                        byte[] buffer = Encoding.UTF8.GetBytes(json);
                        //发送    
                        clientSocket.Send(buffer);
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("AddClientMsg-Send错误信息：" + ex.Message, ex);
                Console.WriteLine("AddClientMsg-DICClientSocket数量" + DICClientSocket.Count.ToString());
                return;
            }
        }

        public static void AddPublicClientMsg(CBaseClass cBaseClass)
        {
            if ((cBaseClass == null))
            {
                return;
            }

            try
            {
                if (DICClientSocket != null && DICClientSocket.Count > 0)
                {
                    List<string> TestList = new List<string>(DICClientSocket.Keys);
                    for (int I = 0; I <= TestList.Count - 1; I++)
                    {
                        if (TestList[I] != cBaseClass.CBaseRemoteEndPointStr)
                        {
                            Socket clientSocket = DICClientSocket[TestList[I]];

                            if ((clientSocket == null) || (clientSocket.Connected == false))
                            {
                                return;
                            }

                            string TypeName = SM_Dictionary[cBaseClass.CBaseClassID];
                            if (!string.IsNullOrEmpty(TypeName))
                            {
                                JsonSerializerSettings jsonSerializerSettings = new JsonSerializerSettings();
                                jsonSerializerSettings.DefaultValueHandling = DefaultValueHandling.Ignore;

                                //序列化为Json格式
                                string json = JsonConvert.SerializeObject(cBaseClass, Type.GetType(TypeName), Formatting.None, jsonSerializerSettings);
                                //编码
                                byte[] buffer = Encoding.UTF8.GetBytes(json);
                                //发送    
                                clientSocket.Send(buffer);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("AddPublicClientMsg错误信息：" + ex.Message, ex);
                Console.WriteLine("AddPublicClientMsg-DICClientSocket数量" + DICClientSocket.Count.ToString());
                return;
            }
        }
    }
}